{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "db7db327-e0d0-4758-82ee-669a7b94484e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-19T05:27:31.520544Z",
     "iopub.status.busy": "2025-11-19T05:27:31.520337Z",
     "iopub.status.idle": "2025-11-19T05:27:31.525260Z",
     "shell.execute_reply": "2025-11-19T05:27:31.524844Z",
     "shell.execute_reply.started": "2025-11-19T05:27:31.520529Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LLM 调用 tools，让LLM 和外界交流\n"
     ]
    }
   ],
   "source": [
    "print(\"LLM 调用 tools，让LLM 和外界交流\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33e82d0e-9285-44a0-86c6-4877d2ab28a5",
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# npm install\n",
    "# 发起请求\n",
    "pip install requests\n",
    "pip install openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "80539556-a195-4437-b4b5-57c5541f5bcb",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-19T05:35:54.192796Z",
     "iopub.status.busy": "2025-11-19T05:35:54.192577Z",
     "iopub.status.idle": "2025-11-19T05:35:54.351346Z",
     "shell.execute_reply": "2025-11-19T05:35:54.350676Z",
     "shell.execute_reply.started": "2025-11-19T05:35:54.192780Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'results': [{'location': {'id': 'WSFXR95RZD21', 'name': '抚州', 'country': 'CN', 'path': '抚州,抚州,江西,中国', 'timezone': 'Asia/Shanghai', 'timezone_offset': '+08:00'}, 'now': {'text': '晴', 'code': '0', 'temperature': '12'}, 'last_update': '2025-11-19T13:20:18+08:00'}]}\n",
      "抚州当前天气：晴, 气温 12度\n"
     ]
    }
   ],
   "source": [
    "import requests\n",
    "# python 类型约定，\n",
    "# js 弱类型语言 \n",
    "# -> str 返回值的类型\n",
    "def get_weather(location: str) -> str:\n",
    "    url = \"https://api.seniverse.com/v3/weather/now.json\"\n",
    "    params = {\n",
    "        \"key\": \"SaVSOt7sYbwpka9iv\",\n",
    "        \"location\": location,\n",
    "        \"language\": \"zh-Hans\"\n",
    "    }\n",
    "    try:\n",
    "        resp = requests.get(url, params=params, timeout=10)\n",
    "        data = resp.json()\n",
    "        print(data)\n",
    "        if \"results\" in data:\n",
    "            r = data[\"results\"][0]\n",
    "            city = r[\"location\"][\"name\"]\n",
    "            # 当前天气对象\n",
    "            now = r[\"now\"]\n",
    "            text = now[\"text\"]\n",
    "            temp = now[\"temperature\"]\n",
    "            #python 擅长机器学习 和字符处理\n",
    "            return f\"{city}当前天气：{text}, 气温 {temp}度\"\n",
    "        else:\n",
    "            return \"查询失败\"\n",
    "    except Exception as e:\n",
    "        return  f\"异常：{e}\"\n",
    "    \n",
    "print(get_weather(\"抚州\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3c8d6544-0c21-48a1-a20e-a46cad1df3de",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-19T05:57:23.357172Z",
     "iopub.status.busy": "2025-11-19T05:57:23.356907Z",
     "iopub.status.idle": "2025-11-19T05:57:23.781595Z",
     "shell.execute_reply": "2025-11-19T05:57:23.781179Z",
     "shell.execute_reply.started": "2025-11-19T05:57:23.357152Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 用户user向llm 提问 自然语言\n",
    "# 实时性的， 工具类的， llm 无法回答\n",
    "# llm和原有的互联网文明桥接起来？ 智能互联网来了\n",
    "# tools 来自openai 接口定义，\n",
    "from openai import OpenAI\n",
    "client = OpenAI(\n",
    "    api_key='sk-f258376fcd7642618c378d8234dcbc4a',\n",
    "    base_url='https://api.deepseek.com/v1'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "5bb24663-b6ec-4d05-a194-21af5ddea676",
   "metadata": {
    "ExecutionIndicator": {
     "show": false
    },
    "execution": {
     "iopub.execute_input": "2025-11-19T06:03:43.876225Z",
     "iopub.status.busy": "2025-11-19T06:03:43.876026Z",
     "iopub.status.idle": "2025-11-19T06:03:43.879100Z",
     "shell.execute_reply": "2025-11-19T06:03:43.878717Z",
     "shell.execute_reply.started": "2025-11-19T06:03:43.876210Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# OpenAI 接口工具定义\n",
    "tools = [\n",
    "    # JSON 定义\n",
    "    {\n",
    "        \"type\": \"function\",\n",
    "         # 函数的申明\n",
    "        \"function\": {\n",
    "            \"name\": \"get_weather\",\n",
    "            \"description\": \"获取指定城市的当前天气\",\n",
    "            \"parameters\": {\n",
    "                \"type\": \"object\",\n",
    "                \"properties\": {\n",
    "                    \"location\": {\n",
    "                        \"type\": \"string\",\n",
    "                         # 北京天气怎么样？提取出北京\n",
    "                        \"description\": \"城市名称，如'北京'\"\n",
    "                    }\n",
    "                },\n",
    "                \"required\": [\"location\"]\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "24549707-a673-4314-903d-8b3dba3fbc6d",
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-11-19T06:12:51.137369Z",
     "iopub.status.busy": "2025-11-19T06:12:51.137135Z",
     "iopub.status.idle": "2025-11-19T06:12:57.306804Z",
     "shell.execute_reply": "2025-11-19T06:12:57.306375Z",
     "shell.execute_reply.started": "2025-11-19T06:12:51.137351Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ChatCompletionMessage(content='我来帮您查询北京的天气情况。', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ChatCompletionMessageFunctionToolCall(id='call_00_jRiQI9N4HYu1ayqoTYKV5kXI', function=Function(arguments='{\"location\": \"北京\"}', name='get_weather'), type='function', index=0)])\n",
      "{'results': [{'location': {'id': 'WX4FBXXFKE4F', 'name': '北京', 'country': 'CN', 'path': '北京,北京,中国', 'timezone': 'Asia/Shanghai', 'timezone_offset': '+08:00'}, 'now': {'text': '晴', 'code': '0', 'temperature': '14'}, 'last_update': '2025-11-19T13:57:33+08:00'}]}\n",
      "根据查询结果，**北京当前天气晴朗，气温14℃**。\n",
      "\n",
      "这是一个比较舒适的天气，适合户外活动。不过北京的天气变化较快，建议您：\n",
      "\n",
      "- 早晚温差可能较大，注意适时增减衣物\n",
      "- 如果长时间在户外，可以做好防晒\n",
      "- 关注最新的天气预报，了解天气变化\n",
      "\n",
      "需要我为您查询更详细的天气信息（如未来几天的预报）吗？\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "messages = [{\"role\": \"user\", \"content\": \"北京天气怎么样\"}]\n",
    "response = client.chat.completions.create(\n",
    "    model = 'deepseek-reasoner',\n",
    "    messages = messages,\n",
    "    tools = tools,\n",
    "    tool_choice = \"auto\",\n",
    "    # 生成的随机度\n",
    "    temperature = 0.3\n",
    ")\n",
    "response_message = response.choices[0].message\n",
    "# 多轮会话\n",
    "print(response_message)\n",
    "# tool_calls ChatCompletionMessageFunctionToolCall\n",
    "messages.append(response_message)\n",
    "if response_message.tool_calls:\n",
    "    for tool_call in response_message.tool_calls:\n",
    "        function_name = tool_call.function.name\n",
    "        # json 字符串变成json 对象\n",
    "        function_args = json.loads(tool_call.function.arguments)\n",
    "        if function_name == \"get_weather\":\n",
    "            function_response = get_weather(function_args[\"location\"])\n",
    "        else:\n",
    "            function_response = \"未知工具\"\n",
    "        messages.append({\n",
    "            \"tool_call_id\": tool_call.id,\n",
    "            \"role\": \"tool\",\n",
    "            \"name\": function_name,\n",
    "            \"content\": function_response\n",
    "        })\n",
    "else:\n",
    "    print(response_message.content)\n",
    "\n",
    "final_response = client.chat.completions.create(\n",
    "    model=\"deepseek-reasoner\",\n",
    "    messages=messages,\n",
    "    temperature=0.3\n",
    ")\n",
    "print(final_response.choices[0].message.content)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
